﻿package net.wangit.view.page;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.wangit.Page;
import net.wangit.Path;
import net.wangit.Unit;
import net.wangit.context.ActionContext;
import net.wangit.context.ActionContextHelper;
import net.wangit.framework.config.DomainsSettings;
import net.wangit.framework.debug.Recorder;
import net.wangit.framework.expression.LabelExpression;
import net.wangit.framework.session.AgileSession;
import net.wangit.framework.util.MessageUtil;
import net.wangit.framework.util.ResponseWriter;
import net.wangit.framework.util.ScriptUtil;
import net.wangit.framework.util.TokenProcessor;
import net.wangit.util.Checker;
import net.wangit.util.StringUtil;
import net.wangit.view.template.Template;
import net.wangit.view.template.TemplateException;
import net.wangit.view.template.TemplateFactory;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.unit.UnitFactory;
import net.wangit.view.unit.util.UnitUtil;


public class PageWriter {

	private static final String WINDOW_TITLE = "window-title";// 浏览器标题
	private static final String HEAD_CONTENT = "head";// head属性
	private static final String SKIN = "skin";// 样式文件路径
	private static final String CSS_INCLUDE = "include-css";// css引用
	private static final String JS_HEAD_INCLUDE = "include-js-first";// 前JS引用
	private static final String JS_TAIL_INCLUDE = "include-js-last";// 后JS引用
	private static final String BODY_ATTRIBUTE = "body-attribute";// body属性
	private static final String HEADING = "heading";// 主标题
	private static final String SUBHEADING = "subheading";// 副标题
	private static final String MESSAGE = "message";// 系统消息
	private static final String UNIT = "unit";// 单元解析结果
	private static final String DEBUG = "debug";// 跟踪内容

	public PageWriter() {
	}

	public static void write(ActionContext ac, PageImpl page) throws Exception {
		Map<String, String> attributes = page.getAttributes();
		Template template = getPageTemplate(page, ac, attributes);
		attributes.put(PageWriter.WINDOW_TITLE,
				LabelExpression.resolve(ac, page.getWindowTitle()));
		UnitComponent uc = page.getUnitComponent();
		attributes.put(PageWriter.HEAD_CONTENT, page.getHead());
		attributes.put(PageWriter.SKIN, Path.getSkin(page.getDomain()));
		attributes.put(PageWriter.CSS_INCLUDE,
				inludeCssPaths(page.getCssPaths(), page.getElementCssPaths()));
		attributes.put(
				PageWriter.JS_HEAD_INCLUDE,
				inludeJsPaths(page.getHeadJsPaths(),
						page.getElementHeadJsPaths()));
		attributes.put(
				PageWriter.JS_TAIL_INCLUDE,
				inludeJsPaths(page.getTailJsPaths(),
						page.getElementTailJsPaths()));
		attributes.put(PageWriter.BODY_ATTRIBUTE, page.getBodyAttribute());
		attributes.put(PageWriter.HEADING, page.getHeading());
		attributes.put(PageWriter.SUBHEADING, page.getSubheading());
		attributes.put(PageWriter.MESSAGE, getMessage());
		attributes.put(PageWriter.UNIT, getUnitHtml(ac, uc)); // 获取单元html
		setRecords(page, attributes);
		String html = template.combine(attributes);
		AgileSession session = ActionContextHelper.getSession(ac);
		String actionScript = session.getActionScript();
		if (!Checker.isEmpty(actionScript))
			page.addTailScript(actionScript);
		List<String> scripts = page.getTailScripts();
		if (!Checker.isEmpty(scripts))
			html = new StringBuilder(html).append(
					ScriptUtil.getActionScript(scripts)).toString();
		ResponseWriter.write(html);
	}

	private static String getUnitHtml(ActionContext ac, UnitComponent uc)
			throws Exception {
		StringBuffer html = new StringBuffer("<input type=\"hidden\" name=\"");
		html.append("_t_").append("\" value=\"")
				.append(TokenProcessor.generateToken(UnitUtil.getKey(uc)))
				.append("\"/>\n");
		html.append(uc.write(ac));
		return html.toString();
	}

	private static Template getPageTemplate(PageImpl page, ActionContext ac,
			Map attributes) {
		String templateName = page.getTemplate();
		if (Checker.isEmpty(templateName))
			templateName = DomainsSettings.getPageTemplate(page.getDomain());
		Template template = TemplateFactory.getTemplate(templateName);
		Map units = template.getUnits();
		String key;
		Iterator keys = units.keySet().iterator();
		while (keys.hasNext()) {
			key = (String) keys.next();
			attributes.put(key, inludeUnitHtml(ac, page, key));
		}
		return template;
	}

	private static void setRecords(PageImpl page, Map attributes) {
		if (Recorder.isEnabled() && !page.getUnitComponent().isPublished()) {
			Recorder.end();
			String tail = (String) attributes.get(PageWriter.DEBUG);
			if (Checker.isEmpty(tail)) {
				attributes.put(PageWriter.DEBUG, Recorder.write());
			} else {
				attributes.put(PageWriter.DEBUG, new StringBuilder(tail)
						.append("<br>").append(Recorder.write()).toString());
			}
		}
	}

	private static String inludeJsPaths(String jsPathsStr,
			Set<String> elementsJsPaths) {
		StringBuffer html = new StringBuffer();
		if (!Checker.isEmpty(jsPathsStr)) {
			String jsPaths[] = StringUtil.split(jsPathsStr, ",");
			for (int i = 0; i < jsPaths.length; i++) {
				inludeJsPath(html, jsPaths[i]);
			}
		}
		Iterator<String> keys = elementsJsPaths.iterator();
		while (keys.hasNext()) {
			inludeJsPath(html, (String) keys.next());
		}
		return html.toString();
	}

	private static void inludeJsPath(StringBuffer html, String jsPath) {
		html.append("<script language=\"JavaScript\" src=\"").append(jsPath)
				.append("\"></script>\n");
	}

	private static String inludeCssPaths(String cssPathsStr,
			Set<String> elementCssPaths) {
		StringBuffer html = new StringBuffer();
		if (!Checker.isEmpty(cssPathsStr)) {
			String cssPaths[] = StringUtil.split(cssPathsStr, ",");
			for (int i = 0; i < cssPaths.length; i++)
				inludeCssPath(html, cssPaths[i]);

		}
		Iterator<String> keys = elementCssPaths.iterator();
		while (keys.hasNext()) {
			inludeCssPath(html, keys.next());
		}
		return html.toString();
	}

	private static void inludeCssPath(StringBuffer html, String cssPath) {
		html.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"")
				.append(cssPath).append("\"/>\n");
	}

	private static String getMessage() {
		return MessageUtil.getMessage();
	}

	private static String inludeUnitHtml(ActionContext ac, Page page, String key) {
		String domain;
		String unitId;
		Unit unit;
		String parameters[] = StringUtil.split(key, ",");
		domain = parameters[0];
		unitId = parameters[1];
		unit = UnitFactory.getUnit(ac, domain, unitId, page);
		try {
			return unit.write(ac);
		} catch (Exception e) {
			throw new TemplateException((new StringBuilder(
					"inlude unit error : ")).append(domain).append("/")
					.append(unitId).toString());
		}
	}
}
